﻿using System;
using System.ComponentModel;
using System.Xml;
using Aeon.Configuration;
using Aeon.Emulator.Dos.VirtualFileSystem;

namespace Aeon.DiskImages
{
    /// <summary>
    /// Base class for disk image configurations.
    /// </summary>
    public abstract class DiskImageConfiguration : AeonConfiguration, IDriveConfiguration
    {
        #region Private Fields
        private string imagePath;
        #endregion

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the DiskImageConfiguration class.
        /// </summary>
        protected DiskImageConfiguration()
        {
            ValidateImageFilePath();
        }
        #endregion

        #region Public Properties
        /// <summary>
        /// Gets a value indicating whether the drive is read-only.
        /// </summary>
        public abstract bool IsReadOnly { get; }
        /// <summary>
        /// Gets or sets the disk image file.
        /// </summary>
        public string ImageFilePath
        {
            get { return this.imagePath; }
            set
            {
                if(this.imagePath != value)
                {
                    this.imagePath = value;
                    OnPropertyChanged(new PropertyChangedEventArgs("ImageFilePath"));
                    ValidateImageFilePath();
                }
            }
        }
        #endregion

        #region Internal Properties
        /// <summary>
        /// Gets the extensions of supported image files.
        /// </summary>
        internal abstract string FileExtensions { get; }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Serializes the configuration to an XML element.
        /// </summary>
        /// <param name="xmlWriter">XmlWriter used to serialize the object.</param>
        protected override void Serialize(XmlWriter xmlWriter)
        {
            if(xmlWriter == null)
                throw new ArgumentNullException("xmlWriter");

            xmlWriter.WriteAttributeString("ImageFilePath", this.ImageFilePath ?? string.Empty);
        }
        /// <summary>
        /// Deserializes the configuration from an XML element.
        /// </summary>
        /// <param name="xmlReader">XmlReader used to deserialize the object.</param>
        protected override void Deserialize(XmlReader xmlReader)
        {
            if(xmlReader == null)
                throw new ArgumentNullException("xmlReader");

            this.ImageFilePath = xmlReader.GetAttribute("ImageFilePath") ?? string.Empty;
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns a new instance of the emulated drive.
        /// </summary>
        /// <returns>New instance of the emulated drive.</returns>
        public abstract IMappedDrive Create();
        /// <summary>
        /// Returns a deep copy of the drive configuration.
        /// </summary>
        /// <returns>Deep copy of the drive configuration.</returns>
        public abstract IDriveConfiguration Clone();
        /// <summary>
        /// Returns a string containing the image file name.
        /// </summary>
        /// <returns>String containing the image file name.</returns>
        public override string ToString()
        {
            return this.ImageFilePath;
        }
        #endregion

        #region Protected Methods
        /// <summary>
        /// Validates the ImageFilePath property.
        /// </summary>
        protected abstract void ValidateImageFilePath();
        #endregion
    }
}
